package cn.redragon.soa.common.util;


import cn.redragon.soa.common.constant.AuthConstant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.MapUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SecurityUtil {

    public static String getProfile() {
        Object principal = getPrincipal();
        return (String) principal;
    }

    /**
     * @return profile
     * @deprecated Replaced by getProfile()
     */
    @Deprecated
    public static String getUser() {
        return getProfile();
    }

    public static String getAccessToken() {
        Object credentials = getCredentials();
        if (credentials != null && Jwt.class.isAssignableFrom(credentials.getClass())) {
            return ((Jwt) credentials).getTokenValue();
        }
        return (String) credentials;
    }
    public static void saveAuthentication(Authentication authentication) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private static Object getPrincipal() {
        return Optional.ofNullable(getAuthentication())
            .map(Authentication::getPrincipal).orElse(AuthConstant.SYSTEM_USER);
    }

    private static Authentication getAuthentication() {
        return Optional.of(SecurityContextHolder.getContext())
            .map(SecurityContext::getAuthentication)
            .orElse(null);
    }

    private static Object getCredentials() {
        return Optional.ofNullable(getAuthentication())
            .map(Authentication::getCredentials).orElse(null);
    }

    public static Collection<? extends GrantedAuthority> getAuthorities() {
        return Optional.ofNullable(getAuthentication())
            .map(Authentication::getAuthorities).orElse(new ArrayList<>());
    }

    public static Collection<String> getSubBrands() {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return new ArrayList<>();
        }
        if (authentication.getClass().isAssignableFrom(JwtAuthenticationToken.class)) {
            JwtAuthenticationToken jwt = (JwtAuthenticationToken) authentication;
            Map<String, Object> claims = jwt.getTokenAttributes();
            if (MapUtils.isNotEmpty(claims)) {
                return new ArrayList<>();
            }
        }
        return new ArrayList<>();
    }


}
